package cc.minos.servers.openfire.ui.textbox
{
	import cc.minos.components.scrollbar.IScrollAbleV;
	import cc.minos.components.scrollbar.IScrollBar;
	import cc.minos.components.scrollbar.ScrollContent;
	import cc.minos.components.textflow.IFontStyle;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Rectangle;
	import flash.text.engine.BreakOpportunity;
	import flash.text.engine.ElementFormat;
	import flash.text.engine.FontPosture;
	import flash.text.engine.FontWeight;
	import flashx.textLayout.compose.StandardFlowComposer;
	import flashx.textLayout.container.ContainerController;
	import flashx.textLayout.container.ScrollPolicy;
	import flashx.textLayout.conversion.ConversionType;
	import flashx.textLayout.edit.EditManager;
	import flashx.textLayout.edit.ISelectionManager;
	import flashx.textLayout.edit.SelectionManager;
	import flashx.textLayout.elements.Configuration;
	import flashx.textLayout.elements.FlowElement;
	import flashx.textLayout.elements.LinkElement;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.events.CompositionCompleteEvent;
	import flashx.textLayout.events.FlowElementMouseEvent;
	import flashx.textLayout.events.StatusChangeEvent;
	import flashx.textLayout.events.TextLayoutEvent;
	import flashx.textLayout.events.UpdateCompleteEvent;
	import flashx.textLayout.formats.TextDecoration;
	import flashx.textLayout.formats.TextLayoutFormat;
	
	/**
	 * ...
	 * 需要textlayout.swc , player 9.0+
	 * @author Minos
	 */
	public class TextBox extends Sprite implements IFontStyle , IScrollAbleV
	{
		public static const INPUT:String = "input";
		public static const DYNAMIC:String = "dynamic";
		
		protected var _flow:TextFlow;
		protected var _controller:ContainerController;
		protected var _manager:ISelectionManager;
		protected var _config:Configuration;
		protected var _composer:StandardFlowComposer;
		
		protected var _type:String;
		protected var _width:Number;
		protected var _height:Number;
		
		protected var _canvas:ScrollContent;
		protected var _scroll:IScrollBar;
		
		protected var _padding:Number = 3;
		
		protected var controllerWidth:Number;
		protected var controllerHeight:Number;
		
		public function TextBox( width:Number = 100 , height:Number = 100 , type:String = DYNAMIC )
		{
			this._type = type;
			this._width = width;
			this._height = height;
			init();
			setSize( width , height );
		}
		
		protected function init():void
		{
			addChildren();
			draw();
		}
		
		protected function addChildren():void
		{
			controllerWidth = _width
			controllerHeight = _height
			
			_canvas = new ScrollContent( controllerWidth , controllerHeight );
			_controller = new CustomController( _canvas , controllerWidth , controllerHeight );
			_controller.paddingLeft = _padding , _controller.paddingRight = _padding;
			_controller.paddingTop = _controller.paddingBottom = _padding;
			
			//_controller.verticalScrollPolicy = ScrollPolicy.OFF;
			//_controller.horizontalScrollPolicy = ScrollPolicy.AUTO;
			
			_config = new Configuration();
			var format:TextLayoutFormat = new TextLayoutFormat();
			format.fontFamily = "微软雅黑,宋体,Arial";
			_config.textFlowInitialFormat = format;
			_composer = new StandardFlowComposer();
			_composer.addController( _controller );
			
			_flow = new TextFlow( _config );
			_flow.fontSize = 12;
			_flow.lineHeight = "120%";
			_flow.color = 0x000000;
			_flow.fontWeight = FontWeight.NORMAL;
			_flow.fontStyle = FontPosture.NORMAL;
			_flow.textDecoration = TextDecoration.NONE;
			
			_flow.breakOpportunity = BreakOpportunity.NONE;
			_flow.flowComposer = _composer;
			
			_flow.linkNormalFormat = { textDecoration: TextDecoration.UNDERLINE };
			_flow.linkHoverFormat = { textDecoration: TextDecoration.NONE };
			
			if ( !_manager )
			{
				if ( _type == INPUT )
					_manager = new EditManager();
				else if ( _type == DYNAMIC )
					_manager = new SelectionManager();
			}
			_flow.interactionManager = _manager;
			
			updateFlow();
			
			addListeners();
			draw();
			addChild( _canvas );
		
		}
		
		/**
		 * add scrollbar interface
		 * 0316
		 * @param	s
		 */
		public function setScrollBar( s:IScrollBar ):void
		{
			_scroll = s;
			if ( _scroll )
			{
				_scroll.target = this;
				
				var skin:DisplayObject = addChild( _scroll.getScrollBar() );
				skin.x = _width - skin.width;
				_controller.setCompositionSize( controllerWidth - skin.width , controllerHeight );
				onScroll( null );
				update();
			}
		}
		
		private function addListeners():void
		{
			_flow.addEventListener( StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE , graphicStatusChangeEvent );
			_flow.addEventListener( CompositionCompleteEvent.COMPOSITION_COMPLETE , composeListener );
			_flow.addEventListener( TextLayoutEvent.SCROLL , onScroll );
			_flow.addEventListener( UpdateCompleteEvent.UPDATE_COMPLETE , onUpdateComplete );
			_flow.addEventListener( FlowElementMouseEvent.CLICK , onLink );
		}
		
		private function removeListeners():void
		{
			_flow.removeEventListener( StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE , graphicStatusChangeEvent );
			_flow.removeEventListener( CompositionCompleteEvent.COMPOSITION_COMPLETE , composeListener );
			_flow.removeEventListener( TextLayoutEvent.SCROLL , onScroll );
			_flow.removeEventListener( UpdateCompleteEvent.UPDATE_COMPLETE , onUpdateComplete );
			_flow.removeEventListener( FlowElementMouseEvent.CLICK , onLink );
		}
		
		private function onUpdateComplete( e:UpdateCompleteEvent ):void
		{
			updateScrollBar();
		}
		
		/**
		 * dispatch a scroll event to update the scrollbar
		 * @param	e
		 */
		private function onScroll( e:TextLayoutEvent ):void
		{
			dispatchEvent( new Event( Event.SCROLL ) );
		}
		
		/**
		 * click name to chat
		 * @param	e
		 */
		private function onLink( e:FlowElementMouseEvent ):void
		{
		/*if ( e.flowElement is LinkElement ) {
		   var link:LinkElement = e.flowElement as LinkElement;
		 }*/
		}
		
		private function graphicStatusChangeEvent( e:StatusChangeEvent ):void
		{
			update();
		}
		
		private function composeListener( e:CompositionCompleteEvent ):void
		{
			update();
		}
		
		private function updateFlow():void
		{
			_composer.updateAllControllers();
		}
		
		public function setSize( width:Number , height:Number ):void
		{
			_width = width;
			_height = height;
			
			var skin:DisplayObject = _scroll ? _scroll.getScrollBar() : null;
			controllerWidth = skin ? ( _width - skin.width ) : _width;
			controllerHeight = _height;
			_controller.setCompositionSize( controllerWidth , controllerHeight );
			if ( skin )
				skin.x = _width - skin.width;
			
			update();
		}
		
		public function update():void
		{
			//draw();
			updateFlow();
			updateScrollBar();
			dispatchEvent( new Event( Event.CHANGE ) );
		}
		
		protected function updateScrollBar():void
		{
			if ( _scroll )
				_scroll.update();
		}
		
		public function draw():void
		{
			this.graphics.clear();
			this.graphics.beginFill( 0xeeeeee , 0 );
			this.graphics.drawRect( 0 , 0 , _width , _height );
			this.graphics.endFill();
		}
		
		public function setFocus():void
		{
			_manager.setFocus();
		}
		
		public function clear():void
		{
			clearText();
			update();
			removeListeners();
			_flow = null;
		}
		
		public function clearText():void
		{
			while ( _flow.numChildren > 0 )
			{
				_flow.removeChildAt( 0 );
			}
			update();
		}
		
		public function get flow():TextFlow
		{
			return _flow;
		}
		
		/* INTERFACE cc.minos.components.IScrollAble */
		
		private const MIN_SCROLL_V:int = 1;
		
		public function get contentHeight():Number
		{
			return _controller[ "contentHeight" ];
		}
		
		public function get scrollV():Number
		{
			return _controller.verticalScrollPosition;
		}
		
		public function set scrollV( value:Number ):void
		{
			var tmp:Number = scrollV;
			if ( value < MIN_SCROLL_V )
				value = MIN_SCROLL_V;
			else if ( value > maxScrollV )
				value = maxScrollV;
			
			_controller.verticalScrollPosition = value + MIN_SCROLL_V;
			
			if ( value != tmp )
				dispatchEvent( new Event( Event.SCROLL ) );
		
		}
		
		public function get maxScrollV():Number
		{
			var val:Number;
			val = MIN_SCROLL_V + 1 + contentHeight - _controller.compositionHeight;
			return val < 1 ? 1 : val;
		}
		
		/* INTERFACE cc.minos.servers.openfire.ui.IFontStyle */
		
		public function get fontFamily():*
		{
			return _flow.fontFamily;
		}
		
		public function set fontFamily( value:* ):void
		{
			_flow.fontFamily = value;
		}
		
		public function get fontSize():*
		{
			return _flow.fontSize;
		}
		
		public function set fontSize( value:* ):void
		{
			_flow.fontSize = value;
		}
		
		public function get color():*
		{
			return _flow.color;
		}
		
		public function set color( value:* ):void
		{
			_flow.color = value;
		}
		
		public function get fontWeight():*
		{
			return _flow.fontWeight;
		}
		
		public function set fontWeight( value:* ):void
		{
			_flow.fontWeight = value;
		}
		
		public function get fontStyle():*
		{
			return _flow.fontStyle;
		}
		
		public function set fontStyle( value:* ):void
		{
			_flow.fontStyle = value;
		}
		
		public function get textDecoration():*
		{
			return _flow.textDecoration;
		}
		
		public function set textDecoration( value:* ):void
		{
			_flow.textDecoration = value;
		}
	
	}

}